#include <stdio.h>
#include <unistd.h>

#include <malloc.h>

#include "list.h"
#include "rc522.h"


LinkList CreateListHead(void)
{
    LinkList L;
    unsigned char i;

    L = (LinkList)malloc(sizeof(struct Node));
    if(L == NULL)
    {
        printf("CreateListHead failed.\r\n");
        // return -1;
    }

    L->data.userid = 0;
    for(i=0;i<NAME_BYTE_LEN;i++)
    {
        L->data.name[i] = 0x00;
    }

    L->data.permission = AUTHORITY_RESERVE;
    L->data.permission_last = AUTHORITY_RESERVE;
    L->data.permission_time_is_forever = YES_YES; //默认永久生效
    L->data.permission_time_hours = 255;
    L->data.permission_time_minutes = 255;
    L->data.permission_time_seconds = 255;

    L->data.scancard_time_is_same = YES_YES;
    L->data.morning_time_hours = 255;
    L->data.morning_time_minutes = 255;
    L->data.morning_time_seconds = 255;
    L->data.afternoon_time_hours = 255;
    L->data.afternoon_time_minutes = 255;
    L->data.afternoon_time_seconds = 255;

    L->next = NULL;

    return L;
}

int Insert(UserInfo *info, LinkList L)
{
    LinkList P, TmpCell; //位置, 新结点
    unsigned char i;

    P = L;

    while(P->next != NULL)
    {
        P = P->next;
    }

    TmpCell = (LinkList)malloc(sizeof(struct Node));
    if(TmpCell == NULL)
    {
        printf("Insert failed, out of space.\r\n");
        return -1;
    }

    //ID
    TmpCell->data.userid = info->userid;
    for(i=0;i<NAME_BYTE_LEN;i++)
    {
        TmpCell->data.name[i] = info->name[i];
    }

    //权限
    TmpCell->data.permission = info->permission;
    TmpCell->data.permission_last = info->permission_last;
    TmpCell->data.permission_time_is_forever = info->permission_time_is_forever;
    TmpCell->data.permission_time_hours = info->permission_time_hours;
    TmpCell->data.permission_time_minutes = info->permission_time_minutes;
    TmpCell->data.permission_time_seconds = info->permission_time_seconds;

    //刷卡(打卡)时间
    TmpCell->data.scancard_time_is_same = info->scancard_time_is_same;
    TmpCell->data.morning_time_hours = info->morning_time_hours;
    TmpCell->data.morning_time_minutes = info->morning_time_minutes;
    TmpCell->data.morning_time_seconds = info->morning_time_seconds;
    TmpCell->data.afternoon_time_hours = info->afternoon_time_hours;
    TmpCell->data.afternoon_time_minutes = info->afternoon_time_minutes;
    TmpCell->data.afternoon_time_seconds = info->afternoon_time_seconds;

    TmpCell->next = NULL;

    P->next = TmpCell;

    return 0;
}

int Delete(UserInfo *info, LinkList L)
{
    LinkList P, TmpCell; //位置, 删除结点

    P = L;

    if(P->next == NULL)
    {
        printf("Delete failed, node not found.\r\n"); //除了头结点之外，无其他结点
        return -1;
    }

    while ((P->next) && (P->next->data.userid != info->userid))
    {
        P = P->next;
    }

    if(P->next == NULL)
    {
        printf("Delete failed, userid not found.\r\n"); //扫描到链尾，没有找到相应结点
        return -2;
    }
    
    TmpCell = P->next;
    P->next = TmpCell->next;
    free(TmpCell);

    return 0;
}

/**
 * @brief  查找结点并返回权限
 * @par  遍历链表，查找结点并返回权限
 * @param  info  [IN] type #UserInfo* 只需传入用户id即可，权限可不用传入。
 * @retval  #-1  没有查找到该结点
 * @retval  #0   查找到该结点，并将权限赋予 info 传出。
*/
int Find_Permission(UserInfo *info, LinkList L)
{
    LinkList P;

    P = L->next;

    while(P != NULL && P->data.userid != info->userid)
    {
        P = P->next;
    }

    if(P == NULL)
    {
        return -1; //扫描到链尾，没有找到相应结点
    }
    else
    {
        info->permission = P->data.permission;
        info->permission_last = P->data.permission_last;
        return 0;
    }
}

/**
 * @brief  查找结点
 * @par  遍历链表，查找结点
 * @param  info  [IN] type #UserInfo* 只需传入用户id即可
 * @retval  #NULL  没有查找到该结点
 * @retval  #UserInfo*  查找到该结点，并返回结点地址。
*/
LinkList Find(UserInfo *info, LinkList L)
{
    LinkList P;

    P = L->next;

    while(P != NULL && P->data.userid != info->userid)
    {
        P = P->next;
    }

    if(P == NULL)
    {
        return NULL; //扫描到链尾，没有找到相应结点
    }
    else
    {
        return P; //找到userid一样的结点
    }
}

//遍历结点，调试
void PrintfList(LinkList L)
{
    LinkList P; //位置
    unsigned int i = 1;

    if (L->next == NULL)
    {
        printf("PrintfList failed, node not found.\r\n"); //除了头结点之外，无其他结点
        return;
    }

    P = L->next;
    
    do{
        printf("UserInfo[%d],userid = [%u],permission = [%d],permission_last = [%d].\r\n", i++, P->data.userid, P->data.permission, P->data.permission_last);
        P = P->next;
    } while(P);
}

void LinkList_Test(void)
{
    LinkList RC522_Database;

    UserInfo user1 = {
        .userid = 123456,
        .name[0] = 0x00,

        .permission = AUTHORITY_USER,
        .permission_last = AUTHORITY_RESERVE,
        .permission_time_is_forever = YES_YES,
        .permission_time_hours = 255,
        .permission_time_minutes = 255,
        .permission_time_seconds = 255,

        .scancard_time_is_same = YES_YES,
        .morning_time_hours = 255,
        .morning_time_minutes = 255,
        .morning_time_seconds = 255,
        .afternoon_time_hours = 255,
        .afternoon_time_minutes = 255,
        .afternoon_time_seconds = 255,
    };
    UserInfo user2 = {
        .userid = 223456,
        .name[0] = 0x00,

        .permission = AUTHORITY_ADMIN,
        .permission_last = AUTHORITY_RESERVE,
        .permission_time_is_forever = YES_YES,
        .permission_time_hours = 255,
        .permission_time_minutes = 255,
        .permission_time_seconds = 255,

        .scancard_time_is_same = YES_YES,
        .morning_time_hours = 255,
        .morning_time_minutes = 255,
        .morning_time_seconds = 255,
        .afternoon_time_hours = 255,
        .afternoon_time_minutes = 255,
        .afternoon_time_seconds = 255,
    };
    UserInfo user3 = {
        .userid = 323456,
        .name[0] = 0x00,

        .permission = AUTHORITY_ROOT,
        .permission_last = AUTHORITY_RESERVE,
        .permission_time_is_forever = YES_YES,
        .permission_time_hours = 255,
        .permission_time_minutes = 255,
        .permission_time_seconds = 255,

        .scancard_time_is_same = YES_YES,
        .morning_time_hours = 255,
        .morning_time_minutes = 255,
        .morning_time_seconds = 255,
        .afternoon_time_hours = 255,
        .afternoon_time_minutes = 255,
        .afternoon_time_seconds = 255,
    };
    UserInfo user4 = {
        .userid = 423456,
        .name[0] = 0x00,

        .permission = AUTHORITY_USER,
        .permission_time_is_forever = YES_YES,
        .permission_time_hours = 255,
        .permission_time_minutes = 255,
        .permission_time_seconds = 255,

        .scancard_time_is_same = YES_YES,
        .morning_time_hours = 255,
        .morning_time_minutes = 255,
        .morning_time_seconds = 255,
        .afternoon_time_hours = 255,
        .afternoon_time_minutes = 255,
        .afternoon_time_seconds = 255,
    };

    UserInfo user5 = {
        .userid = 323456,
        .name[0] = 0x00,
        
        .permission = AUTHORITY_USER,
        .permission_time_is_forever = YES_YES,
        .permission_time_hours = 255,
        .permission_time_minutes = 255,
        .permission_time_seconds = 255,

        .scancard_time_is_same = YES_YES,
        .morning_time_hours = 255,
        .morning_time_minutes = 255,
        .morning_time_seconds = 255,
        .afternoon_time_hours = 255,
        .afternoon_time_minutes = 255,
        .afternoon_time_seconds = 255,
    };

    RC522_Database = CreateListHead();
    printf("CreateListHead:userid = %d, permission = %d.\r\n", RC522_Database->data.userid, RC522_Database->data.permission);

    Insert(&user1, RC522_Database);
    Insert(&user2, RC522_Database);
    Insert(&user3, RC522_Database);
    Insert(&user4, RC522_Database);
    PrintfList(RC522_Database);

    Delete(&user5, RC522_Database);
    PrintfList(RC522_Database);

    UserInfo user6 = {
        .userid = 223456,
    };
    int ret;

    ret = Find_Permission(&user6,RC522_Database);
    if(ret == 0)
    {
        printf("user6:userid = %d, permission = %d.\r\n", user6.userid, user6.permission);
    }
}

void Permission_Time_Pros(LinkList L)
{
	LinkList P; //位置

	if (L->next == NULL)
    {
        printf("PrintfList failed, node not found.\r\n"); //除了头结点之外，无其他结点
    }

	P = L->next;

	do{
		//此时的某个用户的权限不是永久
        if(P->data.permission_time_is_forever != YES_YES) //不是永远，有期限
		{
			//秒>0
			if(P->data.permission_time_seconds > 0)
			{
				P->data.permission_time_seconds--;
			}
			else //秒=0
			{
				//分>0 借位
				if(P->data.permission_time_minutes > 0)
				{
					P->data.permission_time_minutes--;
					P->data.permission_time_seconds = 59;
				}
				else //分=0
				{
					//时>0 借位
					if(P->data.permission_time_hours > 0)
					{
						P->data.permission_time_hours--;
						P->data.permission_time_minutes = 59;
						P->data.permission_time_seconds = 59;
					}
					else //时=0
					{
						//授权时间已剩 0时0分0秒
						P->data.permission = P->data.permission_last; //回复此用户的权限为上一次的权限 permission_last
                        P->data.permission_last = AUTHORITY_RESERVE; //上一次权限初始为 保留
                        P->data.permission_time_is_forever = YES_YES; //永久
					}
				}
			}
		}

        P = P->next;
    } while(P);
}